package com.drcoffee.drcoffeemall.util;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.drcoffee.drcoffeemall.entry.Result;
import com.drcoffee.drcoffeemall.entry.Trade;
import com.drcoffee.drcoffeemall.mapper.OrderMapper;
import com.drcoffee.drcoffeemall.mapper.TradeMapper;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Component
public class AllPayVerifyUtil {
    @Autowired
    TradeMapper tradeMapper;

    @Autowired
    OrderMapper orderMapper;
    /**
     * 应用ID
     */
    @Value("${alipay.app_id}")
    private String ali_app_id;
    /**
     * 商户私钥
     */
    @Value("${alipay.merchant_private_key}")
    private String ali_merchant_private_key;
    /**
     * 支付宝公钥
     */
    @Value("${alipay.alipay_public_key}")
    private String ali_alipay_public_key;
    /**
     * 签名方式
     */
    @Value("${alipay.sign_type}")
    private String ali_sign_type;
    /**
     * 字符编码格式
     */
    @Value("${alipay.charset}")
    private String ali_charset;
    /**
     * 支付宝网关
     */
    @Value("${alipay.gateway_url}")
    private String ali_gateway_url;


    /**
     * 商户号
     */
    @Value("${wechat.merchantId}")
    private String wx_merchantId = "1489444742";

    /**
     * 商户API私钥路径
     */
    @Value("${wechat.privateKeyPath}")
    private String wx_privateKeyPath;

    /**
     * 商户证书序列号
     */
    @Value("${wechat.merchantSerialNumber}")
    private String wx_merchantSerialNumber;

    /**
     * 商户APIV3密钥
     */
    @Value("${wechat.apiV3Key}")
    private String wx_apiV3Key;

    /**
     * @param order_code 订单编号
     * @param type       校验类型
     */
    public Result payVerify(String order_code, Integer type) {
        //微信和支付宝都要校验该订单
        Integer aliResult = aliPayVerify(order_code);
        Integer wxResult = wxPayVerify(order_code);
        if (type == 0) {
            // 跳转付款页时校验
            if (aliResult != 3 && wxResult != 1) {
                // 微信和支付宝都没有订单支付成功记录
                return new Result(1, "订单未支付成功或订单不存在", "", true);
            } else {
                return new Result(1, "订单已支付", "", false);
            }
        } else if (type == 1) {
            // 微信支付时校验支付宝 校验支付宝是否存在未付款订单，存在则关闭支付宝订单后在进行微信支付
            if (aliResult == 3) {
                return new Result(1, "订单已支付", "", false);
            } else {
                return new Result(1, "订单未支付", "", true);
            }
        } else if (type == 2) {
            //支付宝支付时校验微信 校验微信是否存在该订单的付款记录
            if (wxResult == 1) {
                return new Result(1, "订单已支付", "", false);
            } else {
                return new Result(1, "订单未支付", "", true);
            }
        } else {
            return null;
        }
    }

    public Integer aliPayVerify(String order_code) {
        try {
            log.info("=============== 进入aliPayVerify");

            AlipayClient alipayClient = new DefaultAlipayClient(ali_gateway_url, ali_app_id, ali_merchant_private_key, "json", ali_charset, ali_alipay_public_key, ali_sign_type);
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", order_code);
            request.setBizContent(bizContent.toString());
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                String trade_status = response.getTradeStatus();
                if (Objects.equals(trade_status, "WAIT_BUYER_PAY")) {
                    log.info("交易创建，等待买家付款");
                    return 1;
                } else if (Objects.equals(trade_status, "TRADE_CLOSED")) {
                    log.info("未付款交易超时关闭，或支付完成后全额退款");
                    return 2;
                } else if (Objects.equals(trade_status, "TRADE_SUCCESS")) {
                    log.info("交易支付成功");
                    return 3;
                } else if (trade_status == "TRADE_FINISHED") {
                    log.info("交易结束，不可退款");
                    return 4;
                } else {
                    return 0;
                }
            } else {
                if (Objects.equals(response.getSubCode(), "ACQ.TRADE_NOT_EXIST")) {
                    System.out.println("查询的交易不存在");
                    return -2;
                } else if (Objects.equals(response.getSubCode(), "ACQ.INVALID_PARAMETER")) {
                    System.out.println("参数无效");
                    return -3;
                } else if (Objects.equals(response.getSubCode(), "ACQ.SYSTEM_ERROR")) {
                    System.out.println("系统错误");
                    return -4;
                } else {
                    return 0;
                }
            }
        } catch (Exception e) {
            log.error("aliPayVerify异常：", e);
            return -1;
        }
    }

    public Integer wxPayVerify(String order_code) {
        try {
            log.info("=============== 进入wxPayVerify");

            // 定义查询订单需要的参数
            QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new QueryOrderByOutTradeNoRequest();
            queryOrderByOutTradeNoRequest.setMchid(wx_merchantId);
            queryOrderByOutTradeNoRequest.setOutTradeNo(order_code);

            Config config =
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(wx_merchantId)
                            .privateKeyFromPath(wx_privateKeyPath)
                            .merchantSerialNumber(wx_merchantSerialNumber)
                            .apiV3Key(wx_apiV3Key)
                            .build();
            // 构建service
            NativePayService service = new NativePayService.Builder().config(config).build();
            // 查询支付订单
            com.wechat.pay.java.service.payments.model.Transaction result = service.queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest);// 根据商户订单号查询

            Transaction.TradeStateEnum tradeState = result.getTradeState();
            // 判断该订单支付结果
            if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.SUCCESS) {
                log.info("支付成功");
                Integer tradeNum = tradeMapper.getTradeNum(result.getOutTradeNo(), "I");
                if (tradeNum == 0) {
                    // 支付成功，更改订单状态
                    orderMapper.setStatus(result.getOutTradeNo(), "2", "status_time_02", "");
                    Integer payerTotal = result.getAmount().getPayerTotal();// 支付金额(单位分)
                    BigDecimal total = new BigDecimal(String.valueOf(payerTotal)).divide(BigDecimal.valueOf(100));// 单位转换为 元

                    // 存储交易记录
                    Trade trade = new Trade(null, result.getOutTradeNo(), result.getSuccessTime(), result.getTransactionId(), "", total, "I", 1);
                    tradeMapper.saveTrade(trade);
                    orderMapper.setPayMethod(result.getOutTradeNo(), 1);

                }
                return 1;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.REFUND) {
                log.info("转入退款");
                return 2;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.NOTPAY) {
                log.info("未支付");
                return 3;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.CLOSED) {
                log.info("已关闭");
                return 4;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.REVOKED) {
                log.info("已撤销（仅付款码支付会返回）");
                return 5;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.USERPAYING) {
                log.info("用户支付中（仅付款码支付会返回）");
                return 6;
            } else if (tradeState == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.PAYERROR) {
                log.info("支付失败（仅付款码支付会返回）");
                return 7;
            } else {
                return 0;
            }
        } catch (ServiceException e) {
            log.error("wxPayVerify异常(ServiceException)：", e);
            String errorCode = e.getErrorCode();
            if (Objects.equals(errorCode, "ORDER_NOT_EXIST")) {
                log.warn("订单不存在");
                return -2;
            } else {
                log.error("=============== 微信订单查询异常CODE：" + errorCode + e.getErrorMessage());
                Map<String, Object> responseMap = BodyToMapUtil.convertJsonToMap(e.getResponseBody());
                log.error(responseMap.toString());
                return -3;
            }
        } catch (Exception e) {
            log.error("wxPayVerify异常：", e);
            return -1;
        }
    }

    public boolean closeAliPay(String order_code) {
        try {
            log.error("=============== 进入closeAliPay");
            AlipayClient alipayClient = new DefaultAlipayClient(ali_gateway_url, ali_app_id, ali_merchant_private_key, "json", ali_charset, ali_alipay_public_key, ali_sign_type);
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", order_code);
            request.setBizContent(bizContent.toString());
            AlipayTradeCloseResponse response = alipayClient.execute(request);

            Map<String, Object> responseMap = BodyToMapUtil.convertJsonToMap(response.getBody());
            log.error(responseMap.toString());
            if (response.isSuccess()) {
                String msg = (String) responseMap.get("msg");
                if (Objects.equals(msg, "Success")) {
                    return true;
                } else {
                    log.warn("=============== 支付宝订单关闭失败(-2)");
                    return false;
                }
            } else {
                log.warn("=============== 支付宝订单关闭失败(-1)");
                return false;
            }
        } catch (Exception e) {
            log.error("closeAliPay异常：", e);
//            e.printStackTrace();
            return false;
        }
    }
}
